﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit;
using NUnit.Framework;
using EventbriteService;

namespace ClientTests
{
    [TestFixture]
    public class JsonReaderTests
    {
        [Test]
        public void CanParseStringTextTest()
        {
            string text = @"[""this is test""]";
            JsonReader reader = new JsonReader(text);
            var result = reader.Parse() as ArrayList;
            Assert.AreEqual("this is test", (string)result[0]);

        }

        [Test]
        public void CanParseReadNumberTest()
        {
            string test = @"[123, -456, 8.78]";
            JsonReader reader = new JsonReader(test);
            var result = reader.Parse() as ArrayList;
            Assert.AreEqual(3, result.Count);
            Assert.AreEqual(123, (long)result[0]);
            Assert.AreEqual(-456, (long)result[1]);
            Assert.AreEqual(8.78m, (decimal)result[2]);

        }

        [Test]
        public void CanParseOctalTest()
        {
            string octalnum = @"[010,01234,-077,0312]";
            JsonReader reader = new JsonReader(octalnum);
            var result = reader.Parse() as ArrayList;
            Assert.AreEqual(4, result.Count);
            Assert.AreEqual("010", (string)result[0]);
            Assert.AreEqual("01234", (string)result[1]);
            Assert.AreEqual("-077", (string)result[2]);
            Assert.AreEqual("0312", (string)result[3]);
        }

        [Test]
        public void CanParseHexTest()
        {
            string octalnum = @"[0xFF,0xFF,0xabcdef,0xabcdef123456789]";
            JsonReader reader = new JsonReader(octalnum);
            var result = reader.Parse() as ArrayList;
            Assert.AreEqual(4, result.Count);
            Assert.AreEqual("0xFF", (string)result[0]);
            Assert.AreEqual("0xFF", (string)result[1]);
            Assert.AreEqual("0xabcdef", (string)result[2]);
            Assert.AreEqual("0xabcdef123456789", (string)result[3]);
        }

        [Test]
        public void CanParseScientificNotation()
        {
            string sn = @"[0e-10,0E-10,0.15e-3,0.4e10,6.0221418e23]";
            JsonReader reader = new JsonReader(sn);
            var result = reader.Parse() as ArrayList;
            Assert.AreEqual(5, result.Count);
            Assert.AreEqual(0d, (decimal)result[0]);
            Assert.AreEqual(0d, (decimal)result[1]);
            Assert.AreEqual(0.00015d, (decimal)result[2]);
            Assert.AreEqual(4000000000d, (decimal)result[3]);
            Assert.AreEqual(6.0221418e23, (decimal)result[4]);
        }

        [Test]
        public void CanParseUnicodeTest()
        {
            string unicode = @"[""\u0021"", ""\u003c"",""\u003E""]";
            JsonReader reader = new JsonReader(unicode);
            var result = reader.Parse() as ArrayList;
            Assert.AreEqual("!", (string)result[0]);
            Assert.AreEqual("<", (string)result[1]);
            Assert.AreEqual(">", (string)result[2]);

        }

        [Test]
        public void CanParseInfinityTest()
        {
            string infinity = @"[Infinity, -Infinity]";
            JsonReader reader = new JsonReader(infinity);
            var result = reader.Parse() as ArrayList;
            Assert.AreEqual(2, result.Count);
            Assert.IsTrue(double.IsPositiveInfinity((double)result[0]));
            Assert.IsTrue(double.IsNegativeInfinity((double)result[1]));
        }

        [Test]
        public void CanParseNotANumberTest()
        {
            string nan = @"[NaN]";
            JsonReader reader = new JsonReader(nan);
            var result = reader.Parse() as ArrayList;
            Assert.IsTrue(double.IsNaN((double)result[0]));
        }

        [Test]
        public void CanParseNegativeNumbersTest()
        {
            string nums = @"[0.0,-0.1,-1.0,-1.000001,-1E-06, -4.94065645841247E-324,  -89007]";
            JsonReader reader = new JsonReader(nums);
            var result = reader.Parse() as ArrayList;
            Assert.AreEqual(7, result.Count);
            Assert.AreEqual(0.0, (decimal)result[0]);
            Assert.AreEqual(-0.1, (decimal)result[1]);
            Assert.AreEqual(-1.0, (decimal)result[2]);
            Assert.AreEqual(-1.000001, (decimal)result[3]);
            Assert.AreEqual(-0.000001, (decimal)result[4]);
           // Assert.AreEqual(-4.94065645841247E-324, (decimal)result[5]);
            Assert.AreEqual(-89007, (long)result[6]);
        }

        [Test]
        public void CanParseDateTest()
        {
            string date = @"[""1989-01-01T00:00:00Z"",""2000-10-01"", ""22-12-1967 13:30:45""]";
            JsonReader reader = new JsonReader(date);
            var result = reader.Parse() as ArrayList;
            Assert.AreEqual(3, result.Count);
            Assert.AreEqual("1989-01-01T00:00:00Z", (string)result[0]);
            Assert.AreEqual("2000-10-01", (string)result[1]);
            Assert.AreEqual("22-12-1967 13:30:45", (string)result[2]);
        }

        [Test]
        public void CanParseUrlTest()
        {
            string url = @"[""test"", ""https://www.eventbrite.com/l/event-management-online/?ref=sem0brd0ggl0usa0ppca0brand&kw=eventbrite%20ex&cr=34320969729&pkw=eventbrite&pmt=e&plc=&mkwid=stSzY14Ad_dc&pcrid=34320969729&gclid=CLKr3r7DlroCFeIRMwodGREAWA""]";

            JsonReader reader = new JsonReader(url);
            var result = reader.Parse() as ArrayList;
            Assert.AreEqual("test", (string)result[0]);
            string expectedUrl = @"https://www.eventbrite.com/l/event-management-online/?ref=sem0brd0ggl0usa0ppca0brand&kw=eventbrite%20ex&cr=34320969729&pkw=eventbrite&pmt=e&plc=&mkwid=stSzY14Ad_dc&pcrid=34320969729&gclid=CLKr3r7DlroCFeIRMwodGREAWA";
            Assert.AreEqual(expectedUrl, (string)result[1]);
        }

        private const string Paragraph = @"<P><SPAN>'Shaping Light: A Small Flash Workshop' </SPAN></P>";

        [Test]
        public void CanParseHtmlTagsTest()
        {

            string url = string.Format(@"[""{0}""]", Paragraph);
            JsonReader reader = new JsonReader(url);
            var result = reader.Parse() as ArrayList;
            Assert.AreEqual(Paragraph, (string)result[0]);
        }

        [Test]
        public void CanParseEmptyArrayTest()
        {
            string emptyArray = @"[]";
            JsonReader reader = new JsonReader(emptyArray);
            var result = reader.Parse() as ArrayList;
            Assert.AreEqual(0, result.Count);

        }

        [Test]
        public void CanParseEmptyObject()
        {
            string emptyObj = @"{}";
            JsonReader reader = new JsonReader(emptyObj);
            var result = reader.Parse() as Dictionary<string, object>;
            Assert.IsNull(result["jobject"]);

            string emptyWithSpace = @"{  }";
            JsonReader reader2 = new JsonReader(emptyWithSpace);
            var result2 = reader2.Parse() as Dictionary<string, object>;
            Assert.IsNull(result2["jobject"]);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void CanNotParseNotClosedObject()
        {
            string obj = @"{""test"":234 ";
            JsonReader reader = new JsonReader(obj);
            var result = reader.Parse();

        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void CanNotParseWrongProperty()
        {
            string obj = @"{""test""234 }";
            JsonReader reader = new JsonReader(obj);
            var result = reader.Parse();
        }

        [Test]
        public void CanParseObject()
        {
            string json = @"{""user"": {""num"":0x20, ""test_decimal"": 189.89,""test_date"": ""1970-01-01T00:00Z"", ""user_key"": ""12851924066577875603"", ""user_id"": 6558201, ""email"": ""Sam@innovation.com""}}";
            JsonReader reader = new JsonReader(json);
            var result = reader.Parse() as Dictionary<string, object>;

            Assert.IsTrue(result.ContainsKey("jobject"));
            var obj = result["jobject"] as Dictionary<string, object>;
            Assert.IsNotNull(obj);
            Assert.IsTrue(obj.ContainsKey("user"));
            obj = obj["user"] as Dictionary<string, object>;
            Assert.IsNotNull(obj);
            Assert.IsTrue(result.ContainsKey("jobject"));
            obj = obj["jobject"] as Dictionary<string, object>;
            Assert.AreEqual("0x20", (string)obj["num"]);
            Assert.AreEqual(189.89, (decimal)obj["test_decimal"]);
            Assert.AreEqual("1970-01-01T00:00Z", (string)obj["test_date"]);
            Assert.AreEqual("12851924066577875603", (string)obj["user_key"]);
            Assert.AreEqual(6558201, (long)obj["user_id"]);
            Assert.AreEqual("Sam@innovation.com", (string)obj["email"]);
        }

        [Test]
        public void FormatTest()
        {
            UrlRequestBuilder rb = new UrlRequestBuilder();
            Uri request = rb.AddConfiguration(new ConfigurationTest() { AppKey = "test", UserKey = "test" })
                .AddFormat("json")
                .AddRequestBaseUrl()
                .AddRequestMethod("test")
                .Build();
            Assert.AreEqual("v3/", request.Segments[1]);
        }
      
    }

    class ConfigurationTest : IEventBriteConfiguration
    {

        #region IEventBriteConfiguration Members

        public string UserKey
        {
            get;

            set;

        }

        public string AppKey
        {
            get;

            set;

        }

        public string Request
        {
            get;

            set;

        }

        public string MessageFormat
        {
            get;

            set;

        }

        #endregion


        public string RequestURL
        {
            get;

            set;

        }
    }
}
